package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"strconv"
)

// CLI 命令行接口
type CLI struct {
	blockchain *Blockchain
}

// printUsage 打印用法
func (cli *CLI) printUsage() {
	fmt.Println("Usage:")
	fmt.Println("  newblock -data ' ' 向区块链增加块")
	fmt.Println("  listblocks 显示区块链")
}

// validateArgs 校验参数合法性
func (cli *CLI) validateArgs() {
	if len(os.Args) < 2 {
		cli.printUsage() // 显示用法
		os.Exit(1)
	}
}

// addBlock 增加区块
func (cli *CLI) addBlock(data string) {
	cli.blockchain.AddBlock(data) // 增加一个区块
	fmt.Println("Success!")
}

// showBlockChain 展示当前区块链数据
func (cli *CLI) showBlockChain() {
	bci := cli.blockchain.Iterator() // 创建循环迭代器
	for {
		block := bci.Next() // 取得下一个区块
		fmt.Printf("Prev. hash: %x\n", block.PrevHash)
		fmt.Printf("Data: %s\n", block.Data)
		fmt.Printf("Hash: %x\n", block.Hash)
		pow := NewProofOfWork(block) // 校验工作量
		fmt.Printf("Pow: %s\n", strconv.FormatBool(pow.Validate()))
		fmt.Println()
		if len(block.PrevHash) == 0 { // 遇到创世区块终止
			break
		}
	}
}

// Run 启动命令行
func (cli *CLI) Run() {
	cli.validateArgs() // 校验
	// 处理命令行参数
	addblockcmd := flag.NewFlagSet("newblock", flag.ExitOnError)
	showchaincmd := flag.NewFlagSet("listblocks", flag.ExitOnError)

	addBlockData := addblockcmd.String("data", "", "Block data")

	switch os.Args[1] {
	case "newblock":
		err := addblockcmd.Parse(os.Args[2:]) // 解析参数
		if err != nil {
			log.Panic("newblock", err) // 处理错误
		}
	case "listblocks":
		err := showchaincmd.Parse(os.Args[2:]) // 解析参数
		if err != nil {
			log.Panic("listblocks", err) // 处理错误
		}
	default:
		cli.printUsage()
		os.Exit(1)
	}

	if addblockcmd.Parsed() {
		if *addBlockData == "" {
			addblockcmd.Usage()
			os.Exit(1)
		} else {
			cli.addBlock(*addBlockData) // 增加区块
		}
	}

	if showchaincmd.Parsed() {
		cli.showBlockChain() // 显示区块链
	}
}
